<?php

namespace tmcore\base;

use tmcore\interfaces\JobInterface;
use think\queue\Job;
use tmcore\utils\Helper;

abstract class BaseJob implements JobInterface
{
    // 监听默认队列：php think queue:listen --queue
    // 监听自定义队列taskJob：php think queue:listen --queue taskJob

    public int $retry_num = 0;

    abstract function doJob($data);

    abstract function notify($data);

    /**
     * 执行任务
     * @param Job $job
     * @param array $data queue-任务名 data-传递参数 retry_num-重试次数
     */
    public function fire(Job $job, $data):void
    {
        $job_name = $data['job'] ?? 'job'; //任务名
        $retry_num = $data['retry_num'] ?? $this->retry_num; //最大错误次数
        $data = $data['data'] ?? []; //执行数据

        $notify_data = [
            'queue' => $job->getQueue(),
            'job' => $job->getName(),
            'job_name' => $job_name,
            'job_id' => $job->getJobId(),
            'param' => json_encode($data, 320),
            'drive' => $job->getConnection(),
            'retry_num' => $job->attempts() - 1
        ];

        // 执行方法前开始时间
        $notify_data['notify_time'] = time();
        try {
            if (class_exists($notify_data['job'])) {
                $start = microtime(true);
                // 执行业务处理
                $result = $this->doJob($data);
                $notify_data['result_msg'] = $result['msg'];
                if ($result['code'] == 0) {
                    $job->delete(); //任务执行成功后删除
                    $notify_data['result'] = 1;
                    // 获取执行耗时
                    $end = microtime(true);
                    $notify_data['execute_time'] = number_format(($end-$start), 4);
                } else {
                    // 检查任务重试次数，默认每隔一分钟重试一次
                    if ($job->attempts() > $retry_num && $retry_num) {
                        $job->delete();
                    }
                }
            } else {
                $job->delete();
                $notify_data['result_msg'] = $notify_data['job'] . '类不存在';
            }

        } catch (\Exception $e) {
            $job->delete();
            $notify_data['result_msg'] = '队列任务处理失败：' . ' 行号：' . $e->getLine() . '文件：' . $e->getFile() . '错误信息：' . $e->getMessage();
        }
        $this->notify($notify_data);
    }

    /**
     * 执行成功
     * @param array $data
     * @param string $msg
     * @param int $code
     * @return array
     */
    public function success($data = [], $msg = 'success', $code = 0): array
    {
        return [
            'code' => $code,
            'msg' => $msg,
            'data' => $data,
        ];
    }


    /**
     * 执行失败
     * @param string $msg
     * @param int $code
     * @return array
     */
    public function error($msg = '', $code = -1): array
    {
        return [
            'code' => $code,
            'msg' => $msg,
        ];
    }

    /**
     * @param $name
     * @param $arguments
     */
    public function __call($name, $arguments)
    {
        $this->fire(...$arguments);
    }


    /**
     * 异步打印日志
     * @param string $path 相对路径
     * @param array $data 打印数据
     * @return false|int 失败：false,成功：字节数
     */
    public function printLog(string $path, array $data)
    {
        return Helper::printTextLog($path, $data);
    }
}